#include <vector>
#include <sstream>
#include <GL/glut.h>
#include "RenderSystem.h"
#include "WindowStatus.h"
#include "Framework.h"
#include "RenderTarget.h"
#include "glString.h"

//#define DEBUG
GLuint gWVPLocation;

RenderSystem::RenderSystem() :
	mCamera(NULL)
{
	mXrot = 0;
	mXrotInc = 0.1f;
	mYrot = 0;
	mYrotInc = 0.05f;
	mZrot = 0;
	mZrotInc = 0.03f;

	mLight = new Light();
	mLight->setType(Light::LT_POINT);
	mLight->setAmbientColor(0.5, 0.5, 0.5, 1.0);
	mLight->setDiffuseColor(1.0, 1.0, 1.0, 0.0);
	mLight->setSpecularColor(1.0, 1.0, 1.0, 0.0);
	mLight->setPosition(0, 400.0, 0.0);

	mFpsCountRender = mFpsRender = mLastTick = 0;

}

RenderSystem::~RenderSystem() {
	delete mLight;
	delete mCamera;
}

void RenderSystem::LightingSetting(void) {
	//光源
	glLightfv (GL_LIGHT1, GL_AMBIENT, mLight->getAmbientColor().ptr());
	glLightfv (GL_LIGHT1, GL_DIFFUSE, mLight->getDiffuseColor().ptr());
	glLightfv (GL_LIGHT1, GL_SPECULAR, mLight->getSpecularColor().ptr());
	if (mLight->getType() == Light::LT_POINT){
		//点光源
		const Vector3f& vec = mLight->getPosition();
		float light_position[4] = {vec[0], vec[1], vec[2], 1}; 
		glLightfv (GL_LIGHT1, GL_POSITION, light_position);
	}
	else {
	}
	glEnable (GL_LIGHT1);
	glEnable (GL_LIGHTING);

	GLfloat mat_ambient[]= { 0.2f, 0.2f, 0.2f, 0.0f };
	GLfloat mat_diffuse[]= { 1.0f, 1.0f, 1.0f, 0.0f };
	GLfloat mat_specular[]= { 0.2f, 0.2f, 0.2f, 0.0f };
	GLfloat mat_shininess[]= { 1.0f };

	glMaterialfv (GL_FRONT, GL_AMBIENT, mat_ambient);
	glMaterialfv (GL_FRONT, GL_DIFFUSE, mat_diffuse);
	glMaterialfv (GL_FRONT, GL_SPECULAR, mat_specular);
	glMaterialfv (GL_FRONT, GL_SHININESS, mat_shininess); 
}

Camera* RenderSystem::getCamera(void) {
	return mCamera;
}

const Camera* RenderSystem::getCamera(void) const {
	return mCamera;
}

void RenderSystem::RenderFpsUpdate(long ticks) {
	mFpsCountRender++;
	if (ticks - mLastTick > 1000) {
		mLastTick = ticks;
		mFpsRender = mFpsCountRender;
		mFpsCountRender = 0;
	}
}

void RenderSystem::RenderInit(void) {
	int w = WindowStatus::getSingletonPtr()->w;
	int h = WindowStatus::getSingletonPtr()->h;

	glClearColor(0, 0, 0, 0);

	glViewport(0, 0, w, h);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, (GLfloat)w / (GLfloat)h, 5.0f, 50000.0f);

	glShadeModel(GL_SMOOTH);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    glHint(GL_POINT_SMOOTH, GL_NICEST);
    glHint(GL_LINE_SMOOTH, GL_NICEST);
    glHint(GL_POLYGON_SMOOTH, GL_NICEST);
	glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
	glEnable(GL_TEXTURE_2D);
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	LightingSetting();

	//创建Camera
	mCamera = new Camera();

    //字体的初始化不能在OPENGL渲染管理初始化完成之前
    mFont.init("Media/Fonts/Vera.ttf", 20);
}

void RenderSystem::RenderObjName(void) {
	//反馈缓冲区格式
	// ||标记--位置信息--颜色信息--纹理信息
	GLfloat	feedBuf[10];

	typedef std::vector< RenderTarget* >::iterator ObjsIter;
	ObjsIter oiBegin = TargetManager::getSingletonPtr()->mTargetVec.begin();
	ObjsIter oiEnd= TargetManager::getSingletonPtr()->mTargetVec.end();
	for (ObjsIter oi = oiBegin; oi != oiEnd; oi++) {
		glPushMatrix();
		RenderTarget* pTarget = (*oi);
		glMultMatrixf(&(pTarget->mMatrix.transpose()[0][0]));
		glEnable(GL_TEXTURE_2D);

		feedBuf[0] = feedBuf[1] = feedBuf[2] = -1;
		glFeedbackBuffer(3, GL_3D, feedBuf);
		glRenderMode(GL_FEEDBACK);

		glBegin(GL_POINTS);
		glVertex3f(0.0f, 0.0f, 0.0f);
		glEnd();

		glRenderMode(GL_RENDER);

		//如果feed[0] == feed[1] == feed[2] == -1
		//说明（0, 0, 0)在视锥体之外，被裁剪掉了
		if (feedBuf[0] >= 0 && feedBuf[1] >= 0 && feedBuf[2] >= 0) {
            GLString::SetColor(0.0f, 1.0f, 0.0f, 1.0f);
			std::ostringstream oss;
			oss << pTarget->mName << endl;
			GLString::Print2D(feedBuf[1], feedBuf[2], oss.str());
		}

		glPopMatrix();
	}
	int screen_height = WindowStatus::getSingletonPtr()->h;
	GLString::SetColor(0.5f, 0.5f, 0.5f);
	ostringstream oss;
	//打印FPS
	oss.str("");
	oss << "FPS rendering: " << mFpsRender;
	GLString::Print2D(0, screen_height - 80, oss.str());

}

void RenderSystem::RenderModels(void) {

	typedef std::vector< RenderTarget* >::iterator ObjsIter;
	ObjsIter oiBegin = TargetManager::getSingletonPtr()->mTargetVec.begin();
	ObjsIter oiEnd= TargetManager::getSingletonPtr()->mTargetVec.end();
	for (ObjsIter oi = oiBegin; oi != oiEnd; oi++) {
		glPushMatrix();
		
		RenderTarget* pTarget= *oi;
		glMultMatrixf(&(pTarget->mMatrix.transpose()[0][0]));


        pTarget->draw();

		glPopMatrix();
	}
}

/*
 * 描述: 画背景格
 * 参数：无
 * 说明：无
 */
void RenderSystem::RenderGrid(void) {
	float tile = 50;
	float x_min = -500, x_max = 500;
	float y_min = -500, y_max = 500;
	float z_min = -500, z_max = 500;

	glDisable(GL_LIGHTING);
	glDisable(GL_TEXTURE_2D);

    glColor3f(0, 0.8, 0);
    glLineWidth(1);
	glBegin(GL_LINES);
	for (float x = x_min; x <= x_max; x += tile) {
		glVertex3f(x, 0, z_min);
		glVertex3f(x, 0, z_max);
	}
	for (float z = z_min; z <= z_max; z += tile) {
		glVertex3f(x_min, 0, z);
		glVertex3f(x_max, 0, z);
	}
	glEnd();
    //x轴
    glColor3f(1, 0, 0);
    glLineWidth(4);
	glBegin(GL_LINES);
    glVertex3f(0, 0, 0);
    glVertex3f(x_max, 0, 0);
	glEnd();
    //y轴
    glColor3f(1, 1, 0);
	glBegin(GL_LINES);
    glVertex3f(0, 0, 0);
    glVertex3f(0, y_max, 0);
	glEnd();
    //z轴
    glColor3f(0, 0, 1);
	glBegin(GL_LINES);
    glVertex3f(0, 0, 0);
    glVertex3f(0, 0, z_max);
	glEnd();

	glEnable(GL_LIGHTING);
	glEnable(GL_TEXTURE_2D);
}

void RenderSystem::RenderLighting(void) {
    //在光源处画一个点
    //让光源旋转,便于观察光源的效果
	//const Vector3f& vec = mLight->getPosition();
    const int r = 200;
    static float rot = 0.01f;
    Vector4f vec(r * Math::Sin(rot), 0, r * Math::Cos(rot), 1);
    rot += 0.001f;
    glLightfv (GL_LIGHT1, GL_POSITION, vec.ptr());


    glPushMatrix();
    glTranslatef(vec.x, vec.y, vec.z);

    glColor3f(1, 1, 1);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_LIGHTING);
    glDisable(GL_LIGHT1);

    glutSolidSphere(5, 32, 32);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT1);

    glPopMatrix();
}

void RenderSystem::RenderDisplay(void) {
	//std::cout << "RenderDisplay." << std::endl;
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

    mCamera->OnRender();

    //绘制网格
	RenderGrid();

    //绘制光源
    RenderLighting();

    //绘制模型
	RenderModels();

	//RenderObjName();
    
    glColor4f(0, 1, 0, 1);
    freetype::print(mFont, 20, 10, "FreeType");


	glFlush();

	FrameworkSwapBuffers();

}
